package com.cskaoyan.order.mq;

import com.cskaoyan.mall.commons.exception.BizException;
import com.cskaoyan.mall.order.constant.OrderRetCode;
import com.cskaoyan.order.constant.OrderConstants;
import com.cskaoyan.order.dal.entitys.Order;
import com.cskaoyan.order.dal.entitys.OrderItem;
import com.cskaoyan.order.dal.entitys.Stock;
import com.cskaoyan.order.dal.persistence.OrderItemMapper;
import com.cskaoyan.order.dal.persistence.OrderMapper;
import com.cskaoyan.order.dal.persistence.StockMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

import static com.cskaoyan.order.constant.OrderConstants.STOCK_RELEASE;

/**
 * @program: csmall-practice
 * @description: 延迟取消订单的消费者
 * @author: Lexis
 * @create: 2022-05-23 19:11
 **/
@Slf4j
@Component
public class DelayOrderCancelConsumer {

    @Autowired
    OrderMapper orderMapper;

    @Autowired
    OrderItemMapper orderItemMapper;

    @Autowired
    StockMapper stockMapper;

    private DefaultMQPushConsumer consumer;


    @PostConstruct
    public void init() {
        consumer = new DefaultMQPushConsumer("delay_order_cancel_consumer");

        consumer.setNamesrvAddr("127.0.0.1:9876");

        consumer.setMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {

                // 在这里实现订单超时自动取消的逻辑
                // 1. 从message获取orderId
                try {
                    MessageExt message = list.get(0);
                    byte[] body = message.getBody();
                    String orderId = new String(body, 0, body.length, StandardCharsets.UTF_8);

                    // 2. 根据orderId, 查询订单的状态，如果订单的状态是已支付, 或者已取消，什么都不做
                    Order order = orderMapper.selectByPrimaryKey(orderId);
                    if (order != null && (OrderConstants.ORDER_STATUS_PAYED == order.getStatus() || OrderConstants.ORDER_STATUS_TRANSACTION_CANCEL == order.getStatus())) {
                        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                    }
                    // 3. 如果订单的状态初始化，那说明订单没有支付成功，执行订单自动取消
                    if (order != null && OrderConstants.ORDER_STATUS_INIT == order.getStatus()) {
                        //    a. 修改订单状态为已取消
                        Order updateOrderStatus = new Order();
                        updateOrderStatus.setOrderId(orderId);
                        updateOrderStatus.setStatus(OrderConstants.ORDER_STATUS_TRANSACTION_CANCEL);
                        updateOrderStatus.setUpdateTime(new Date());
                        updateOrderStatus.setCloseTime(new Date());
                        int updateRows = orderMapper.updateByPrimaryKeySelective(updateOrderStatus);
                        if (updateRows < 1) {
                            throw new BizException(OrderRetCode.DB_EXCEPTION.getCode(), OrderRetCode.DB_EXCEPTION.getMessage());
                        }
                        //    b. 根据OrderId，获取订单中的所有订单商品条目，根据每一个订单商品条目购买的数量
                        // 更新库存表
                        Example example = new Example(OrderItem.class);
                        example.createCriteria().andEqualTo("orderId", orderId);
                        List<OrderItem> orderItems = orderItemMapper.selectByExample(example);
                        for (OrderItem orderItem : orderItems) {
                            Integer num = orderItem.getNum();
                            Stock stock = new Stock();
                            stock.setItemId(orderItem.getItemId());
                            stock.setStockCount(Long.valueOf(num));
                            stock.setLockCount(-num);
                            stockMapper.updateStock(stock);
                        }
                        // 更新库存状态
                        orderItemMapper.updateStockStatus(STOCK_RELEASE, orderId);

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });

        try {
            consumer.subscribe("delay_order_cancel", "*");
            consumer.start();
            log.debug("消费者消费成功");
        } catch (MQClientException e) {
            e.printStackTrace();
        }
    }
}
